// --------------------头文件引入部分--------------------
#include <iostream>
#include <vector>
#include <stack>
#include <unordered_set>
#include <string>
#include <fstream>
#include <algorithm>
#include <unordered_map>
#include <queue>
#include <set>
#include <map>
// #include <functional>
using namespace std;

// --------------------数据结构定义部分--------------------
// 符号表项(类别，正则表达式，编号)
typedef struct
{
    string category;
    string regular_expression;
    int id;
} Item;

typedef struct
{
    Item item;
    string list;
} Token;

// 符号表
vector<Item> config;

// 正则表达式中的约定字符
unordered_set<string> type_char{"N", "C", "L", "P", "D"};
// N,C,L,P分别表示数字，大写字母，小写字母，正数
unordered_set<string> number{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
unordered_set<string> capital_letter{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
unordered_set<string> lowercase_letter{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
unordered_set<string> positive_number{"1", "2", "3", "4", "5", "6", "7", "8", "9"};
unordered_set<string> syms{" ","=", ">", "<", "/", "*", "|", "&", "_",";", "{", "}", "%", "!", "+", "-", ",", "(", ")"};
unordered_set<string> all_char;

// 类声明
class NFAEdge;
class NFANode;
class NFAStruct;
class DFAStruct;

// NFA边
class NFAEdge
{
public:
    string symbol;                                        // 边上的符号
    NFANode *start;                                       // 起始节点
    NFANode *end;                                         // 结束节点
    NFAEdge(NFANode *start, NFANode *end, string symbol); // 构造函数
    void connectEdge();                                   // 用边连接两节点
};

// NFA节点
class NFANode
{
public:
    static int NFACount; // NFA节点数
    bool is_final;       // 是否是终止节点
    int index;           // 节点索引
    // int id;                                   // 符号id,仅在终止节点有效，其他节点恒为0
    Item item;                                    // 只有每个终止节点有效，表示config中的某一项，也是词法分析器的输出
    vector<NFAEdge *> InEdge;                     // 入边列表
    vector<NFAEdge *> OutEdge;                    // 出边列表
    NFANode(Item i = {}, bool final = false); // 构造函数
};

// NFAStruct
class NFAStruct
{
public:
    vector<NFAEdge *> edges;                                                                                        // 边列表
    NFANode *startNode;                                                                                             // 起始节点
    vector<NFANode *> endNode;                                                                                      // 终止节点
    NFAStruct(NFANode *start = nullptr, vector<NFANode *> end = vector<NFANode *>{}, vector<NFAEdge *> edges = {}); // 构造函数
};

NFAStruct NFA; // 最终完整的NFA成品

// DFAStruct
// DFA状态：初始点集及或某弧转换后的点集和一些附加属性
class DFAStruct
{
public:
    vector<int> NFANum; // 存储NFA节点的索引列表
    bool is_final;      // 表示当前状态是否为终止状态，默认为False
    // int id;                                        // 当前状态对应的值，默认为0
    Item item;                  // 终止节点所需的信息
    vector<NFANode *> NFANodes; // 存储NFA节点列表
    vector<int> FinHash;        // 终点索引列表
    // 后面用于重载 == !=
    size_t hash;
    string str;
    DFAStruct(vector<NFANode *> listNFA = vector<NFANode *>{}, bool is_final = false, vector<int> FinHash = {});
    bool operator==(const DFAStruct &other);
    bool operator!=(const DFAStruct &other);
    bool operator<(const DFAStruct &other) const;
};

map<DFAStruct, map<string, DFAStruct>> converse_table = {}; // DFA转换表，类似一个二维表，状态DFAStruct的string弧转换
DFAStruct initial_node;                                     // 初始DFS，即NFA初始节点的epsilon闭包

// 正则表达式的运算符
const unordered_set<string> REG_OPS = {"$(", "$|", "$*", "$+"};

// --------------------类成员函数定义部分--------------------
int NFANode::NFACount = 0;

NFANode::NFANode(Item i, bool final)
{
    is_final = final;
    // id = id_;
    item = i;
    index = NFACount;
    NFACount++;
}

NFAEdge::NFAEdge(NFANode *start, NFANode *end, string symbol)
{
    this->start = start;
    this->end = end;
    this->symbol = symbol;
    connectEdge();
}

void NFAEdge::connectEdge()
{
    start->OutEdge.push_back(this); // 将边添加到起始节点的出边列表中
    end->InEdge.push_back(this);    // 将边添加到结束节点的入边列表中
}

NFAStruct::NFAStruct(NFANode *start, vector<NFANode *> end, vector<NFAEdge *> edges)
{
    this->startNode = start;
    this->endNode = end;
    this->edges = edges;
}

DFAStruct::DFAStruct(vector<NFANode *> listNFA, bool is_final, vector<int> FinHash)
{
    this->is_final = is_final;
    this->NFANodes = listNFA;
    this->FinHash = FinHash;
    this->item = {};
    this->hash = 0;
    this->str = "";
    vector<string> tmpstring = {};
    std::hash<string> strhash;    // 字符串哈希函数
    for (NFANode *node : listNFA) // 遍历DFAStruct中所有节点
    {
        if (find(FinHash.begin(), FinHash.end(), node->index) != FinHash.end()) // 如果是终止节点
            this->item = node->item;                                            // 将终止节点信息放入DFAStruct，这里没有考虑DFAStruct中包含多个NFA终点的情况，不过好像这种情况不会出现
        this->NFANum.push_back(node->index);
        tmpstring.push_back(to_string(node->index)); // 每个节点值放入tmpstring
    }
    sort(tmpstring.begin(), tmpstring.end());
    for (string &s : tmpstring)
    {
        this->str += s;
        this->str += " ";
    }
    this->hash = strhash(this->str);
}

bool DFAStruct::operator==(const DFAStruct &other)
{
    return this->hash == other.hash;
}

bool DFAStruct::operator!=(const DFAStruct &other)
{
    return this->hash != other.hash;
}

bool DFAStruct::operator<(const DFAStruct &other) const
{
    return this->hash < other.hash;
}

// --------------------普通函数定义部分--------------------
// 读入配置，初始化符号表
void init_allchar()
{
    all_char.insert(number.begin(), number.end());
    all_char.insert(capital_letter.begin(), capital_letter.end());
    all_char.insert(lowercase_letter.begin(), lowercase_letter.end());
    all_char.insert(type_char.begin(), type_char.end());
    all_char.insert(syms.begin(),syms.end());
}

void init_config()
{
    init_allchar();
    ifstream file("config.txt");
    if (file.is_open())
    {
        string line;
        while (getline(file, line))
        {
            // 解析每一行并创建 Item 对象
            string delimiter = "~";
            size_t pos = line.find(delimiter);
            if (pos != string::npos)
            {
                string category = line.substr(0, pos);
                line.erase(0, pos + delimiter.length());
                pos = line.find(delimiter);
                if (pos != string::npos)
                {
                    string regular_expression = line.substr(0, pos);
                    string idStr = line.substr(pos + delimiter.length());
                    int id = stoi(idStr);
                    // 创建 Item 对象并添加到 vector
                    Item item;
                    item.category = category;
                    item.regular_expression = regular_expression;
                    item.id = id;
                    config.push_back(item);
                }
            }
        }
        file.close();
    }
    else
    {
        cout << "Failed to open the file config.txt." << endl;
    }
}

// generate_NFA的辅助函数，处理正则表达式
// 将正则表达式转换为NFA
// 在隐式构建抽象语法树的过程中使用汤普森算法构建NFA
// 注：构造抽象语法树时不考虑运算符的优先级，因为在config中已经手动划分了
NFAStruct *handle_regular_expression(string input)
{
    stack<string> ops;           // 运算符栈
    stack<NFAStruct *> vals;     // 值栈
    bool skip_mode = false;      // 跳过模式标志
    input = "$(" + input + "$)"; // 在正则表达式前后添加特殊符号$，表示起始和结束
    string::size_type index = 0; // 正则表达式中的元素索引
    while (index < input.length())
    {
        string current_char = string(1, input[index]);
        if (skip_mode) // skip_mode = true说明上一轮用了一个&*，这一轮需要将index再移动一次
        {
            skip_mode = false;
            index++;
            continue;
        }
        if (current_char == "$")
        {
            current_char += input[index + 1]; // 将$和后一个字符合并成一个字符
            skip_mode = true;
        }
        if (REG_OPS.find(current_char) != REG_OPS.end()) // 如果是正则表达式的运算符
        {
            ops.push(current_char); // 将运算符入栈
        }
        else if (current_char == "$)") // 如果是$)，需要先将（）内的运算完
        {
            while (!ops.empty() && ops.top() != "$(") // 当运算符栈非空且栈顶运算符不是$(
            {
                string top_op = ops.top(); // 获取栈顶运算符
                ops.pop();                 // 弹出栈顶运算符
                if (top_op == "$|")        // 如果是$|
                {
                    NFANode *start = new NFANode();   // 创建起始节点
                    NFANode *end = new NFANode();     // 创建终止节点
                    NFAStruct *prev_val = vals.top(); // 弹出前一个值
                    vals.pop();
                    NFAStruct *next_val = vals.top(); // 弹出后一个值
                    vals.pop();
                    NFAEdge *edge1 = new NFAEdge(start, prev_val->startNode, "EPSILON"); // 创建连接起始节点和前一个值起始节点的EPSILON边
                    NFAEdge *edge2 = new NFAEdge(start, next_val->startNode, "EPSILON"); // 创建连接起始节点和后一个值起始节点的EPSILON边
                    NFAEdge *edge3 = new NFAEdge(prev_val->endNode[0], end, "EPSILON");  // 创建连接前一个值终止节点和终止节点的EPSILON边
                    NFAEdge *edge4 = new NFAEdge(next_val->endNode[0], end, "EPSILON");  // 创建连接后一个值终止节点和终止节点的EPSILON边
                    vector<NFAEdge *> new_edges = {edge1, edge2, edge3, edge4};
                    new_edges.insert(new_edges.end(), prev_val->edges.begin(), prev_val->edges.end());
                    new_edges.insert(new_edges.end(), next_val->edges.begin(), next_val->edges.end());
                    NFAStruct *nfa_struct = new NFAStruct(start, vector<NFANode *>{end}, new_edges);
                    vals.push(nfa_struct); // 将生成的NFAStruct压入值栈
                }
                else if (top_op == "$+") // 如果是$+
                {
                    NFAStruct *next_val = vals.top(); // 弹出后一个值
                    vals.pop();
                    NFAStruct *prev_val = vals.top(); // 弹出前一个值
                    vals.pop();
                    NFANode *first_end = prev_val->endNode[0];   // 前一个值的终止节点
                    NFANode *second_start = next_val->startNode; // 后一个值的起始节点
                    for (NFAEdge *edge : prev_val->edges)        // 注：这种方法有改变，旧前一个NFA的终止节点被遗弃
                    {
                        if (edge->end == first_end)
                        {
                            edge->end = second_start; // 将连接前一个值终止节点的边的结束节点改为后一个值起始节点
                        }
                    }
                    NFAStruct *nfa_struct = new NFAStruct(prev_val->startNode, next_val->endNode, prev_val->edges);
                    nfa_struct->edges.insert(nfa_struct->edges.end(), next_val->edges.begin(), next_val->edges.end());
                    vals.push(nfa_struct); // 将生成的NFAStruct压入值栈
                }
                else if (top_op == "$*") // 如果是$*
                {
                    NFAStruct *val = vals.top(); // 弹出值
                    vals.pop();
                    NFANode *start = new NFANode();                                           // 创建起始节点
                    NFANode *end = new NFANode();                                             // 创建终止节点
                    NFAEdge *edge1 = new NFAEdge(start, end, "EPSILON");                      // 创建连接起始节点和终止节点的ε边
                    NFAEdge *edge2 = new NFAEdge(start, val->startNode, "EPSILON");           // 创建连接起始节点和值起始节点的ε边
                    NFAEdge *edge3 = new NFAEdge(val->endNode[0], end, "EPSILON");            // 创建连接值终止节点和终止节点的ε边
                    NFAEdge *edge4 = new NFAEdge(val->endNode[0], val->startNode, "EPSILON"); // 创建连接值终止节点和值起始节点的ε边
                    vector<NFAEdge *> new_edges = {edge1, edge2, edge3, edge4};
                    new_edges.insert(new_edges.end(), val->edges.begin(), val->edges.end());
                    NFAStruct *nfa_struct = new NFAStruct(start, vector<NFANode *>{end}, new_edges);
                    vals.push(nfa_struct); // 将生成的NFAStruct压入值栈
                }
            }
        }
        else // 如果是普通字符
        {
            if (index >= 2 && REG_OPS.find(input.substr(index - 2, 2)) == REG_OPS.end()) // 如果是两个连续的普通字符，中间要加一个+号
            {
                ops.push("$+"); // 将$+入栈
            }
            NFANode *start = new NFANode();                        // 创建起始节点
            NFANode *end = new NFANode();                          // 创建终止节点
            NFAEdge *edge = new NFAEdge(start, end, current_char); // 创建连接起始节点和终止节点的边,边上的符号就是某字符，如a，b
            vector<NFAEdge *> edges = {edge};
            NFAStruct *nfa_struct = new NFAStruct(start, vector<NFANode *>{end}, edges); // 创建包含边的NFAStruct
            vals.push(nfa_struct);                                                       // 将NFAStruct压入值栈
        }
        index++;
    }
    return vals.top(); // 返回值栈中的第一个值
}

// 生成NFA
void generate_NFA()
{
    vector<NFAStruct *> nfas; // 存储单个正则表达式的nfa列表
    for (Item item : config)
    {
        NFAStruct *nfa = handle_regular_expression(item.regular_expression);
        nfas.push_back(nfa);
    }
    // 到目前，每个小nfa都只有一个开始节点和一个终止节点
    NFANode *all_start = new NFANode();        // 完整NFA的起始节点
    NFAStruct complete_NFA(all_start, {}, {}); // 创建完整的NFA结构对象
    // int current_id = 1;
    int cur_config_order = 0;
    for (NFAStruct *nfa : nfas) // 遍历NFA列表中的每个NFA
    {
        // 添加终止节点信息
        nfa->endNode[0]->is_final = true;                 // 末尾节点标志
        nfa->endNode[0]->item = config[cur_config_order ++]; // 末尾节点需要的输出属性，IDN和INT还未处理
        // 创建一个连接起始节点和NFA起始节点的ε边
        NFAEdge *edge = new NFAEdge(all_start, nfa->startNode, "EPSILON");
        complete_NFA.edges.push_back(edge);                                                        // 将连接起始节点和NFA起始节点的ε边添加到完整NFA的边列表中
        complete_NFA.edges.insert(complete_NFA.edges.end(), nfa->edges.begin(), nfa->edges.end()); // 将NFA的边列表添加到完整NFA的边列表中
        // nfa->endNode[0]->id = current_id++;                                                        // 末尾节点加id
        // nfa->endNode[0]->is_final = true;                                                          // 末尾节点标志
        complete_NFA.endNode.push_back(nfa->endNode[0]); // 将NFA的终止节点添加到完整NFA的终止节点列表中
    }
    NFA = complete_NFA; // 返回完整的NFA结构
    return;
}

// generate_DFA的辅助函数，求epsilon闭包，输入待求节点集和终止节点集，返回DFAStruct
DFAStruct epsilon_closure(vector<NFANode *> input, vector<NFANode *> endNodes)
{
    // 终止节点集合的索引列表
    vector<int> endNodesHash = {};
    for (NFANode *node : endNodes)
        endNodesHash.push_back(node->index);
    bool flag = false; // 终止状态标志
    // Item cur_item = {};
    vector<NFANode *> result = input;                   // 求闭包的结果
    // stack<NFANode *, vector<NFANode *>> mystack(input); // 节点栈，用vector作为底层容器
    // queue<NFANode *, vector<NFANode *>> myqueue(input);
    queue<NFANode *> myqueue;
    for(auto in : input)
    {
        myqueue.push(in);
    }
    while (!myqueue.empty())                            // 如果栈不空
    {
        NFANode *ele = myqueue.front();
        myqueue.pop();
        if (find(endNodesHash.begin(), endNodesHash.end(), ele->index) != endNodesHash.end()) // 看当前节点是否是终止节点
        {
            flag = true;
            // cur_item = ele->item;
        }
        for (NFAEdge *edge : ele->OutEdge) // 遍历当前节点所有出边
        {
            // 边是epsilon，边的终点不在result里
            if (edge->symbol == "EPSILON" && (find(result.begin(), result.end(), edge->end) == result.end()))
            {
                result.push_back(edge->end);
                myqueue.push(edge->end);
            }
        }
    }
    // result是所求的闭包集合
    // flag表示求出来的闭包含有终点节点，即当前求出的点集在DFA中可以变成一个终点
    // endNodesHash终止节点集合的索引列表
    // cur_item表示闭包集合的item，当节点集中有终点时，cur_item为终点item，否则为空，暂只考虑闭包集合中仅有一个终点（应该只会出现这种情况吧）
    return DFAStruct(result, flag, endNodesHash);
}

// 某弧转换：先求当前闭包的Move，再求闭包
// now：当前状态(某闭包)，sheet：DFA转换表，all_D：所有状态集合，endNodes：终点集合
void cal_nxt(DFAStruct now, map<DFAStruct, map<string, DFAStruct>> &sheet, set<DFAStruct> &all_D, vector<NFANode *> endNodes)
{
    for (string s : all_char)
    {
        vector<NFANode *> temp_list; // Move(now, s)
        // 求Move(now, s)
        for (NFANode *node : now.NFANodes)
        {
            for (NFAEdge *edge : node->OutEdge)
            {
                if (edge->symbol == s)
                    temp_list.push_back(edge->end);
            }
        }
        if (temp_list.size() == 0) // Move(now, s)为空，直接求下一个Move
            continue;
        DFAStruct nxt = epsilon_closure(temp_list, endNodes); // 求Move后的闭包
        if (all_D.find(nxt) == all_D.end())                   // 如果nxt是新的状态
        {
            all_D.insert(nxt);
            sheet[nxt] = {};
        }
        if (sheet.find(now) == sheet.end()) // 如果now不在DFA转换表中
        {
            sheet[now] = {};
            sheet[now][s] = nxt;
        }
        else
            sheet[now][s] = nxt;
    }
}

// 将完整的NFA转化为DFA：构造出了DFA表
void generate_DFA()
{
    set<DFAStruct> all_D = {};  // 存储所有DFAStruct集合
    set<DFAStruct> sign_D = {}; // 存储处理过的DFAStruct集合，即这个状态的这一整行都求出来了
    initial_node = epsilon_closure(vector<NFANode *>{NFA.startNode}, NFA.endNode);
    all_D.insert(initial_node);
    while (all_D.size() - sign_D.size() != 0)
    {
        set<DFAStruct> difference = {};
        set_difference // 将all_D和sign_D的差集装入difference
            (
                all_D.begin(), all_D.end(),
                sign_D.begin(), sign_D.end(),
                insert_iterator<set<DFAStruct>>(difference, difference.begin()));
        DFAStruct now = *difference.begin();              // 差集中的第一个元素，即第一个未处理状态
        sign_D.insert(now);                               // 处理它
        cal_nxt(now, converse_table, all_D, NFA.endNode); // 计算这一行DFA表
        // minimize_DFA();
    }
}

// 最小化DFA
void minimize_DFA()
{
    // converse_table = converse_table;
    // initial_node = initial_node;
}

/*bool isLegal(string &symbol, set<string> symbols)
{
    bool flag = false;
    if (symbols.find(symbol) != symbols.end())
        flag = true;
    else if (symbols.find("N") != symbols.end() && number.find(symbol) != number.end())
    {
        symbol = "N";
        flag = true;
    }
    else if (symbols.find("C") != symbols.end() && capital_letter.find(symbol) != number.end())
    {
        symbol = "C";
        flag = true;
    }
    else if (symbols.find("L") != symbols.end() && lowercase_letter.find(symbol) != number.end())
    {
        symbol = "L";
        flag = true;
    }
    else if (symbols.find("P") != symbols.end() && positive_number.find(symbol) != number.end())
    {
        symbol = "P";
        flag = true;
    }
    else if (symbols.find(symbol) != symbols.end())
        flag = true;
    return flag;
}*/

bool isLegal1(string &symbol, set<string> symbols)
{
    bool flag = false;
    if (symbols.find(symbol) != symbols.end())
        flag = true;
    return flag;
}

bool isLegal2(string &symbol, set<string> symbols)
{
    bool flag = false;
    if(symbols.find("D") != symbols.end() && symbol == ".")
    {
        symbol = "D";
        flag = true;
    }
    else if (symbols.find("N") != symbols.end() && number.find(symbol) != number.end())
    {
        symbol = "N";
        flag = true;
    }
    else if (symbols.find("C") != symbols.end() && capital_letter.find(symbol) != number.end())
    {
        symbol = "C";
        flag = true;
    }
    else if (symbols.find("L") != symbols.end() && lowercase_letter.find(symbol) != number.end())
    {
        symbol = "L";
        flag = true;
    }
    else if (symbols.find("P") != symbols.end() && positive_number.find(symbol) != number.end())
    {
        symbol = "P";
        flag = true;
    }
    else if (symbols.find(symbol) != symbols.end())
        flag = true;
    return flag;
}

void output(vector<Token> token_list, const string &out_path)
{
    ofstream outputFile(out_path);
    if (outputFile.is_open())
    {
        for (Token &token : token_list)
        {
            if(token.list[0] == ' ')
            {
                token.list = token.list.substr(1);
            }
            if (token.item.category == "IDN" || token.item.category == "INT" || token.item.category == "FLOAT")
                outputFile << token.list << " <" << token.item.category << "," << token.list << ">" << endl;
            else
                outputFile << token.list << " <" << token.item.category << "," << token.item.id << ">" << endl;
        }
    }
    else
        printf("File does not exist.");
    outputFile.close();
}

// 扫描输入的C--程序进行匹配
void scan(const string &path, const string &out_path)
{
    ifstream inputFile(path);
    if (inputFile.is_open())
    {
        string total;
        getline(inputFile, total, '\0');
        total = ' ' + total;
        replace(total.begin(), total.end(), '\t', ' ');
        replace(total.begin(), total.end(), '\n', ' ');
        replace(total.begin(), total.end(), '\r', ' ');
        total.erase(unique(total.begin(), total.end(), [](char a, char b)
                           { return a == ' ' && b == ' '; }),
                    total.end()); // 删除连续空格，只保留一个
        int p = 0;
        int late_pointer = 0; // 识别到的单词末尾字符
        vector<Token> token_list = {};
        string symbol = " ";
        int value_start_pointer = 0; // 当前单词开头前面一个字符
        DFAStruct check_point_token; // 识别到单词的终止状态
        bool check_point_token_valid = false;
        DFAStruct this_state = initial_node; // 当前状态
        bool is_second = false;
        bool the_first_time = false;
        bool one_more_chance = true;
        while (p <= total.size())
        {
            if (p < total.size())
                symbol = total[p]; // 当前符号
            if (symbol == ".")
            {
                p += 1;
                symbol = total[p]; // 当前符号
            }  
            set<string> symbols = {}; // 所有可识别符号
            for (const auto &pair : converse_table[this_state])
                symbols.insert(pair.first);
            // 两步合法性判断
            bool flag = false;
            if(!is_second)
            {
                flag = isLegal1(symbol, symbols);
                if(!check_point_token_valid)
                {
                    if(flag == false)
                    {
                        is_second = true;
                        the_first_time = true;
                        if(one_more_chance)
                        {
                            if(total[p] == ' ')
                            {
                                is_second = false;
                                the_first_time = false;
                            }
                            one_more_chance = false;
                        }
                    }
                }
            }
            if(is_second)
            {
                if(the_first_time)
                {
                    if(total[value_start_pointer + 1] == ' ')
                        p = p  = value_start_pointer + 2;
                    else p  = value_start_pointer + 1;
                    symbols = {};
                    symbol = total[p];
                    this_state = initial_node;
                    for (const auto &pair : converse_table[this_state])
                        symbols.insert(pair.first);
                    the_first_time = false;
                }
                flag = isLegal2(symbol, symbols);
            }
            if (flag && p != total.size())
            {
                DFAStruct next_state = converse_table[this_state][symbol];
                if (next_state.is_final)
                {
                    check_point_token = next_state;
                    check_point_token_valid = true;
                    late_pointer = p;
                }
                this_state = next_state;
            }
            else
            {
                if (check_point_token_valid == true)
                {
                    Item tmp = check_point_token.item;
                    Token token = {};
                    token.item = tmp;
                    token.list = total.substr(value_start_pointer + 1, late_pointer - value_start_pointer);
                    if(token.list.find_first_of('.') != string::npos)
                    {
                        token.item.category = "FLOAT";
                    }
                    token_list.push_back(token);
                    one_more_chance = true;
                    is_second = false;
                    check_point_token_valid = false;
                    // if(total[late_pointer + 1] == ' ')
                    //     value_start_pointer = late_pointer + 1;
                    // else
                    //     value_start_pointer = late_pointer;
                    value_start_pointer = late_pointer;
                    p = value_start_pointer;
                    this_state = initial_node;
                    if (p == total.size() - 1)
                        break;
                }
                else
                {
                    is_second = false;
                    printf("Unrecognized character '%c', occurred in the %dth character.\n", total[p],p);
                }
                    
            }
            p += 1;
        }
        output(token_list, out_path);
    }
    else
        printf("File does not exist.");
    inputFile.close();
}

// 主函数
int main()
{
    init_config();                           // 得到全局变量config符号表
    generate_NFA();                          // 构建NFA，放入全局变量NFA
    generate_DFA();                          // NFA确定化
    minimize_DFA();                          // DFA最小化
    scan("./01_var_defn.txt", "./lexical_01_var_defn.txt"); // 扫描C--进行匹配
    return 0;
}
